#![allow(dead_code)]

use std::{future::Future, str::FromStr};

use chrono::Local;
use cron::Schedule;
use tokio::time::{self, Instant};

pub fn job<F, R>(cron: &str, mut handle: F)
where
    F: FnMut() -> R + Sync + Send + 'static,
    R: Future<Output = ()> + Send + 'static,
{
    let schedule = Schedule::from_str(cron).unwrap();
    tokio::spawn(async move {
        for datetime in schedule.upcoming(Local) {
            let sec_total = (datetime - Local::now()).num_seconds() as u64;
            let start = Instant::now() + time::Duration::from_secs(sec_total);
            let mut timer = time::interval_at(start, time::Duration::from_secs(600));
            timer.tick().await;
            handle().await;
        }
    });
}

pub fn job_params<F, R, T>(cron: &str, params: T, handle: F)
where
    F: Fn(T) -> R + Sync + Send + 'static,
    T: Send + Clone + Sync + 'static,
    R: Future<Output = ()> + Send + 'static,
{
    let schedule = Schedule::from_str(cron).unwrap();
    let p: T = params.clone();
    tokio::spawn(async move {
        for datetime in schedule.upcoming(Local) {
            let sec_total = (datetime - Local::now()).num_seconds() as u64;
            let start = Instant::now() + time::Duration::from_secs(sec_total);
            let mut timer = time::interval_at(start, time::Duration::from_secs(600));
            timer.tick().await;
            handle(p.clone()).await;
        }
    });
}
